package tool

import (
	"fmt"
	"openmanus/llm"

	logger "github.com/axcom/ninego/log"
)

// ToolResult 表示工具执行的结果
type ToolResult struct {
	Output interface{} `json:"output,omitempty"`
	Text   string      `json:"text,omitempty"`
	Error  string      `json:"error,omitempty"`
}

// BaseTool 所有工具的基本接口
type BaseTool interface {
	// Name 获取工具名称
	Name() string

	// Description 获取工具描述
	Description() string

	// Parameters 获取工具参数模式
	Parameters() llm.Schema /*map[string]interface{}*/

	// Execute 执行工具
	Execute(args map[string]interface{}) (*ToolResult, error)

	// ToParam 转换为函数调用格式
	ToParam() llm.Tool

	// Cleanup 清理工具资源
	Cleanup() error
}

// ToolBase 提供基础工具功能的实现
type ToolBase struct {
	toolName        string
	toolDescription string
	toolParameters  llm.Schema
}

// NewToolBase 创建新的工具基础实例
func NewToolBase(name, description string, parameters llm.Schema) *ToolBase {
	return &ToolBase{
		toolName:        name,
		toolDescription: description,
		toolParameters:  parameters,
	}
}

// Name 获取工具名称
func (t *ToolBase) Name() string {
	return t.toolName
}

// Description 获取工具描述
func (t *ToolBase) Description() string {
	return t.toolDescription
}

// Parameters 获取工具参数模式
func (t *ToolBase) Parameters() llm.Schema {
	return t.toolParameters
}

// ToParam 转换为函数调用格式
func (t *ToolBase) ToParam() llm.Tool {
	return llm.Tool{
		Name:        t.Name(),
		Description: t.Description(),
		InputSchema: t.Parameters(),
	}
}

// Cleanup 清理工具资源（默认实现）
func (t *ToolBase) Cleanup() error {
	return nil
}

// SuccessResponse 创建成功的工具结果
func SuccessResponse(data interface{}) *ToolResult {
	logger.Debug("Created success response")
	switch data.(type) {
	case string:
		return &ToolResult{Text: data.(string)}
	default:
		return &ToolResult{Output: data}
	}
}

// FailResponse 创建失败的工具结果
func FailResponse(msg string) *ToolResult {
	logger.Debug("Tool returned failed result: %s", msg)
	return &ToolResult{Error: msg}
}

// StringResult 将结果转换为字符串表示
func (tr *ToolResult) StringResult() string {
	if tr.Error != "" {
		return tr.Error
	}
	if tr.Text != "" {
		return tr.Text
	}
	if tr.Output != nil {
		if str, ok := tr.Output.(string); ok {
			return str
		}
		return fmt.Sprintf("%v", tr.Output)
	}
	return ""
}
